#include "mid_link.h"


static link_private_t m_link_data;

//---------------------------------------------------------------------------------
// Ӳ�����?
#include "mid_Debug.h"

#define LINK_LOG_EN 1
#if LINK_LOG_EN
#include "mid_Debug.h"
#define LogMask_link  ((ELOG_Error | ELOG_Warning | ELOG_Trace | ELOG_Info) & LogMask_Globle)
#define link_log_array(type,tag, arr,arr_len) if ((type) & LogMask_link) Mid_Debug_Sprintf_u8Array(type, tag, arr,arr_len)
#define link_log(type,tag, formate, ...) if ((type) & LogMask_link) Mid_Debug_Sprintf(type, tag, formate, ##__VA_ARGS__)
#else
#define link_log_array(type,tag, formate, ...) (void*)0
#define link_log(type,tag, formate, ...) (void*)0

#endif


#define LINK_ASSERT(...)
#define LINK_PRINTF(...)

#if DOWNLOAD_USE_DEBUG_PORT
#define LinkPort_Init			UART0_Init
#define LinkPort_Deinit			UART0_DeInit
#define LinkPort_Read			UART0_Read
#define LinkPort_Write			UART0_Write
#define LinkPort_WriteByte		UART0_WriteByte
#else
#define LinkPort_Init			UART1_Init
#define LinkPort_Deinit			UART1_DeInit
#define LinkPort_Read			UART1_Read
#define LinkPort_Write			UART1_Write
#define LinkPort_WriteByte		UART1_WriteByte
#endif
extern uint8_t ArmReadyFlag; 
//---------------------------------------------------------------------------------
void mid_link_initpin(void )
{
	// LinkPort_InitPin();
}

uint8_t g_mid_link_inited = 0;
void mid_link_init(void )
{
	// 清除m_data;
	uint8_t* node = (uint8_t*)&m_link_data;
	for (uint16_t i = 0; i <sizeof(link_private_t); i++)
	{
		node[i] = 0;
	}

	LinkPort_Init();
	g_mid_link_inited = 1;
}

void mid_link_deinit(void)
{
	LinkPort_Deinit();
	g_mid_link_inited = 0;
}

//---------------------------------------------------------------------------------

static void mid_link_encrypt(link_frame_t* frame)
{
	//加密 frame中的data域，结果再写回data域
	uint8_t data_len = frame->frame_len - 9;
	
	data_len = data_len;
}

static void mid_link_decrypt(link_frame_t* frame)
{	
	//解密 frame中的data域，结果再写回data域
	uint8_t data_len = frame->frame_len - 9;
	
	data_len = data_len;
}

//CRC16_XMODEM：多项式x16+x12+x5+1（0x1021），初始值0x0000，低位在后，高位在前，结果与0x0000异或
uint16_t mid_link_crc16_xmodem(uint8_t *bin, uint8_t bin_len)
{
	uint16_t crc = 0x0000;
	uint16_t poly = 0x1021;
	uint16_t wchar  = 0;

	while (bin_len--) 	
	{
		wchar = *(bin++);
		crc ^= (wchar << 8);
		for(int i = 0;i < 8;i++)
		{
			if(crc & 0x8000)
				crc = (crc << 1) ^ poly;
			else
				crc = crc << 1;
		}
	}
	return (crc) ;
}

//---------------------------------------------------------------------------------

static void mid_link_tx(uint8_t bin[], uint8_t bin_len) //TODO: 这里要节约用栈
{
	uint16_t len = bin_len; //如果没有转译发生, 要写入串口的字节数就这么多.
	uint16_t len_writed = 0;
	
	if(g_mid_link_inited==0)	return;
		
	len_writed += LinkPort_WriteByte(bin[0]);
	len_writed += LinkPort_WriteByte(bin[1]);
	for(uint16_t i= 2; i < bin_len; i++)
	{
		if (bin[i-1]==0x55 && (bin[i]==0xAA || bin[i]==0x5A))
		{
			len_writed += LinkPort_WriteByte(0x5A);
			len++;
		}
		len_writed += LinkPort_WriteByte(bin[i]);
	}

	LINK_ASSERT(len_writed == len, __FUNCTION__##": Tx Data Failed!, Buffer is Full"); //发送失败, 主mcu可能发送的断帧给soc
}


static void mid_link_tx_ack(link_frame_t* frame)
{
	uint8_t bin[9]; 
	uint8_t bin_len = 0;

	LINK_ASSERT((frame->frame_type & LINK_FrameType_ACKBit)==0, __FUNCTION__##": frame_type is Wrong!");
	
	bin[bin_len++] = 0x55;//frame_head_h;
	bin[bin_len++] = 0xAA;//frame_head_l;
	bin[bin_len++] = 0x09;//frame_len;
	bin[bin_len++] = frame->frame_number;
	bin[bin_len++] = frame->frame_type | LINK_FrameType_ACKBit;
	bin[bin_len++] = (uint8_t)(((frame->addr>>4)&0x0F) | ((frame->addr<<4)&0xF0)); //交换src dts
	bin[bin_len++] = frame->op;

	uint16_t crc16 = mid_link_crc16_xmodem(bin, bin_len);
	bin[bin_len++] = (uint8_t)(crc16 >> 8);
	bin[bin_len++] = (uint8_t)(crc16 >> 0);

	LINK_ASSERT(bin_len < sizeof(bin), __FUNCTION__##": bin[] is overflow");
	mid_link_tx(bin, bin_len);
}


static void mid_link_tx_msg(link_frame_t* tx_frame)
{
	mid_link_tx(tx_frame->bin, tx_frame->frame_len);
}


//---------------------------------------------------------------------------------

link_rx_t g_link_rx;

static void mid_link_rx_make(uint8_t data_in)
{
	static uint8_t data_last = 0;
	
	//正常报文帧
	if (data_last == 0x55 && data_in == 0xAA) //收到了帧头
	{
		g_link_rx.rx_state = STLINK_RxLen;
		g_link_rx.rx_count = 0;
		g_link_rx.rx_buffer.bin[g_link_rx.rx_count++] = 0x55;
		g_link_rx.rx_buffer.bin[g_link_rx.rx_count++] = 0xAA;
		data_last = data_in;
		return;
	}
	else if (data_last == 0x55 && data_in == 0x5A)//收到了转译:收到了555A,则将5A丢弃
	{
		data_last = data_in;
		return;
	}
	
	data_last = data_in;
	switch (g_link_rx.rx_state)
	{
		case STLINK_RxHead:
		break;
		
		case STLINK_RxLen:
			g_link_rx.rx_buffer.bin[g_link_rx.rx_count++] = data_in;
			if (g_link_rx.rx_buffer.frame_len < 9)//帧长度太短
			{
				LINK_PRINTF(__FUNCTION__##": frame_len is to short");
				g_link_rx.rx_state = STLINK_RxHead;
				break;
			}
			g_link_rx.rx_state = STLINK_RxEnd;
		break;
		
		case STLINK_RxEnd:
			g_link_rx.rx_buffer.bin[g_link_rx.rx_count++] = data_in;
			if (g_link_rx.rx_count == g_link_rx.rx_buffer.frame_len)
			{
				if (mid_link_crc16_xmodem(g_link_rx.rx_buffer.bin, g_link_rx.rx_count) == 0x0000)
				{
					//soc发给主mcu的frame, 则缓存,交由上层处理, 并在这里回ack.
					if ((g_link_rx.rx_buffer.addr & FrameAddrDst_Mask) == FrameAddrDst_MainMcu)
					{
						if (g_link_rx.rx_buffer.frame_type & LINK_FrameType_ACKBit)
						{
							g_link_rx.rx_ack_valid = 1;//收到的ack帧未及时被取出的话，在这里会被覆盖掉
							g_link_rx.rx_ack_frame = g_link_rx.rx_buffer;
						}
						else
						{
							g_link_rx.rx_msg_valid = 1;//收到的msg帧未及时被取出的话，在这里会被覆盖掉
							g_link_rx.rx_msg_frame = g_link_rx.rx_buffer;
							
							// mid_link_tx_ack(&g_link_rx.rx_buffer);//发出ack
						}
					}
				}
				else
				{
					//校验失败
					LINK_PRINTF(__FUNCTION__##": Check Sum Error");
				}
				g_link_rx.rx_state = STLINK_RxHead;
			}
		break;
			
		default:
			LINK_ASSERT(0,__FUNCTION__##": Invalid State");
		break;
	}
}


static uint8_t mid_link_is_rightack(link_frame_t* tx_frame, link_frame_t* ack_frame)
{
	//TODO: 这里还要判断源目地址是否对得上
	if (tx_frame->frame_number != ack_frame->frame_number)
		return 0;
		
	if ((tx_frame->frame_type | LINK_FrameType_ACKBit) != ack_frame->frame_type)
		return 0;
		
	return 1;
}


//---------------------------------------------------------------------------------

void mid_link_1ms_timer(void)
{
	m_link_data.state_timer++;
}

void mid_link_service(void)
{
	//uint32_t heartbeat_gap;
	uint8_t data_in[150]; //最短的帧为7个字节，data_in[]数组不能装下两帧,以免引起覆盖
	if (g_mid_link_inited == 0)
		return;
		
	// 1.接收帧
	while(1)
	{
		uint8_t data_len = LinkPort_Read(data_in, sizeof(data_in));
		if (data_len == 0)
			break;
		for(uint8_t i = 0; i < data_len; i++)
		{
			mid_link_rx_make(data_in[i]);
		}
		if (g_link_rx.rx_ack_valid || g_link_rx.rx_msg_valid || g_link_rx.rx_msg_valid_soc2can)
			break; // 本函数退出前必须把收到的msg或ack处理掉
	}

	// 2.发送帧
	link_srv_state_t state = m_link_data.state;
	switch(m_link_data.state)
	{
		case STLINK_Reset:
			mid_link_init();
			m_link_data.state = STLINK_TxIdle;
			m_link_data.link_ok = 0;
		break;

		case STLINK_TxIdle:
			if (m_link_data.tx_result == LinkTxMsg_Busy)
			{
				m_link_data.state   = STLINK_TxFrame;
				m_link_data.tx_repeat  = 0;
			}

			/*heartbeat_gap = m_link_data.link_ok ? 1000 : 3000;
			if (m_link_data.state_timer > heartbeat_gap)
			{
				m_link_data.tx_heartbeat_number++;
				m_link_data.tx_heartbeat_valid = 1;
			}*/
		break;

		case STLINK_TxFrame:
			mid_link_tx_msg(&m_link_data.tx_msg_frame);
			m_link_data.tx_repeat++;
			m_link_data.state   = STLINK_WaitAck;
		break;

		case STLINK_WaitAck:
			if (g_link_rx.rx_ack_valid)
			{
				g_link_rx.rx_ack_valid = 0;
				if (mid_link_is_rightack(&m_link_data.tx_msg_frame, &g_link_rx.rx_ack_frame))//对方回应了ack，成功发送一帧数据
				{					
					m_link_data.tx_msg_valid = 0;
					m_link_data.tx_result = LinkTxMsg_Success;
					m_link_data.state = STLINK_TxIdle;
					m_link_data.link_ok = 1;
					break;
				}
			}
			
			if (m_link_data.state_timer > LINK_TxTimeout_Max)
			{
				if (m_link_data.tx_repeat < LINK_TxRepeat_Max)
				{
					m_link_data.state = STLINK_TxFrame;
				}
				else
				{
					//m_link_data.tx_msg_valid = 0;     //暂定为：重新建链，再次发送。TODO:最佳做法是什么
					m_link_data.tx_result = LinkTxMsg_Failed;
					m_link_data.state = STLINK_Reset;
					m_link_data.link_ok = 0;
					link_log(ELOG_Trace, "link","link Tx reset !!!\r\n");
				}
			}
		break;

		default:
			LINK_ASSERT(0,__FUNCTION__##": Invalid tx state");
		break;
	}
	if (state != m_link_data.state) //发生了状态迁移
	{
		m_link_data.state_enter = 0;
		m_link_data.state_timer = 0;
	}
}

//读取soc发给主mcu的消息
uint8_t mid_link_getmsg(link_frametype_t * type, uint16_t * cmd, uint8_t* data[], uint8_t* data_len)
{
	if (g_link_rx.rx_msg_valid == 0)
		return 0;

	g_link_rx.rx_msg_valid = 0;
	
	if (g_link_rx.rx_msg_frame.frame_type & LINK_FrameType_EncryptBit)
	{
		mid_link_decrypt(&g_link_rx.rx_msg_frame); //对帧中msg进行解密
	}
		
	*type = (link_frametype_t)(g_link_rx.rx_msg_frame.frame_type);
	*cmd  = ((uint16_t)g_link_rx.rx_msg_frame.addr << 8) + g_link_rx.rx_msg_frame.op;
	*data = &g_link_rx.rx_msg_frame.msg[0];
	*data_len = g_link_rx.rx_msg_frame.frame_len - 9;
	return 1;	
}


//主mcu发消息给soc, 则缓存, 稍后由发送状态机发出.
uint8_t mid_link_sendmsg_from_app(link_frametype_t type, uint16_t cmd, uint8_t data[], uint8_t data_len)
{
	if (m_link_data.tx_result == LinkTxMsg_Busy) //上一帧还未发出，不能发新的帧
		return 0;

	LINK_ASSERT((type & LINK_FrameType_ACKBit)==0, __FUNCTION__##": Param Error,Invalid type!");
	LINK_ASSERT(data_len < (LINK_FrameLen_Max - 9), __FUNCTION__##": data_len is too large");
	
    //将要发出的消息缓存一下
	uint8_t index = 0;
	m_link_data.tx_msg_frame.bin[index++] = 0x55;
	m_link_data.tx_msg_frame.bin[index++] = 0xAA;
	m_link_data.tx_msg_frame.bin[index++] = (uint8_t)(data_len + 9);
	m_link_data.tx_msg_frame.bin[index++] = m_link_data.tx_number++;

	m_link_data.tx_msg_frame.bin[index++] = (uint8_t)type;
	m_link_data.tx_msg_frame.bin[index++] = (uint8_t)(cmd >> 8);
	m_link_data.tx_msg_frame.bin[index++] = (uint8_t)(cmd >> 0);

	for(uint8_t i = 0; i < data_len; i++)
	{
		m_link_data.tx_msg_frame.bin[index++] = data[i];
	}

	if (type & LINK_FrameType_EncryptBit) //对帧中msg进行加密
	{
		mid_link_encrypt(&m_link_data.tx_msg_frame);
	}

	uint16_t crc16 = mid_link_crc16_xmodem(m_link_data.tx_msg_frame.bin, index);
	m_link_data.tx_msg_frame.bin[index++] = (uint8_t)(crc16 >> 8);
	m_link_data.tx_msg_frame.bin[index++] = (uint8_t)(crc16 >> 0);

	mid_link_tx_msg(&m_link_data.tx_msg_frame); //TODO: 直接发到串口不经过发送状态机了（临时方案，因为发送状态机效率太低，无法应对上层突发的消息发送需求）。
	
	//m_link_data.tx_msg_valid = 1;
	//m_link_data.tx_result = LinkTxMsg_Busy;
	
	return 1;
}


link_tx_result_t mid_link_getresult(void) //获取发送结果
{
	return LinkTxMsg_Success;//m_link_data.tx_result;
}


uint8_t mid_link_isconnect(void)
{
	return m_link_data.link_ok;
}


//---------------------------------------------------------------------------------
// 使用示例
#if 0

void calc_crc(void)
{
	uint8_t dat[] = {0x55, 0xAA, 0x0B, 0x00, 0x02, 0x23, 0x91, 0x01, 0x02};
	uint16_t crc16 =0;
	crc16 = mid_link_crc16_xmodem(dat, sizeof(dat));
	crc16 = crc16;
}

#include "mid_uart1.h"

int mid_link_test_service(void) //���յ�����Ϣ����
{
	static uint8_t step = 0;
	static uint32_t tick = 0;

    switch(step)
    {
    	case 0:
    		mid_link_init();
    		step = 1;
    	break;

    	case 1:
    		mid_link_service();

    		link_frametype_t type;
    		uint16_t cmd;
    		uint8_t* data;
    		uint8_t  data_len;
    		if (mid_link_getmsg(&type, &cmd, &data, &data_len))
    		{
    			//�յ���Ϣ������response
    			mid_link_sendmsg_from_app(LINK_FrameType_Response, cmd, data, data_len);
    		}
    	break;

    	case 2:
    		mid_link_deinit();
    	break;
    }

    if (tick < g_systick) 
    {
    	tick = g_systick;
    	mid_link_1ms_timer();
    }
    return 0;
}

#endif

